package server

import (
	"../chess"
	"../conf"
	"flag"
	"github.com/gorilla/websocket"
	"log"
	"net/http"
	"strings"
	"time"
)

const (
	// Time allowed to write a message to the peer.
	writeWait = 10 * time.Second

	// Time allowed to read the next pong message from the peer.
	pongWait = 60 * time.Second

	// Send pings to peer with this period. Must be less than pongWait.
	pingPeriod = (pongWait * 9) / 10

	// Maximum message size allowed from peer.
	maxMessageSize = 512
)

//var (
//	newline = []byte{'\n'}
//	space   = []byte{' '}
//)

var upgrader = websocket.Upgrader{
	ReadBufferSize:  1024,
	WriteBufferSize: 1024,
}

var addr = flag.String("addr", ":8080", "http service address")

func StartServer() {
	flag.Parse()
	pm := build()
	http.HandleFunc("/", http_handler)

	http.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) {
		ws_handler(&pm, w, r)
	})

	err := http.ListenAndServe(*addr, nil)
	if err != nil {
		log.Fatal("ListenAndServe: ", err)
	}
}

func http_handler(w http.ResponseWriter, r *http.Request) {
	log.Println(r.URL)
	if r.URL.Path != "/" {
		http.Error(w, "Not found", http.StatusNotFound)
		return
	}
	if r.Method != "GET" {
		http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
		return
	}
	http.ServeFile(w, r, "home.html")
}

func ws_handler(pm *matcher, w http.ResponseWriter, r *http.Request) {
	connection, err := upgrader.Upgrade(w, r, nil)
	if err != nil {
		conf.Logger.Error(err)
		return
	}
	go read_message(pm, connection)
}

func read_message(pm *matcher, ws *websocket.Conn) {
	ws.SetReadLimit(maxMessageSize)
	ws.SetReadDeadline(time.Now().Add(pongWait))
	ws.SetPongHandler(func(string) error { ws.SetReadDeadline(time.Now().Add(pongWait)); return nil })
	for {
		var message user_message
		err := ws.ReadJSON(message)
		if err != nil {
			conf.Logger.Error(err)
			break
		}
		if strings.Compare("match", message.operate) == 0 {
			player := chess.Player{1, 9, 0, message.id, ws}
			pm.match(&player)
			break
		} else {
			conf.Logger.Warn("Unknown message %s", message.operate)
			time.Sleep(time.Millisecond * 200)
		}
	}
}

type user_message struct {
	id      uint32
	operate string
}
